import time
import threading

from contextlib import asynccontextmanager
from fastapi import FastAPI, Request
from fastapi.staticfiles import StaticFiles
from fastapi.middleware.gzip import GZipMiddleware
from fastapi.middleware.cors import CORSMiddleware

from .config import appSettings
from application.routers import init_web_routers, init_api_routers
from sanren.extensions import setup_logging


class Application:
    def __init__(self):
        @asynccontextmanager
        async def lifespan(app: FastAPI):
            # 启动前执行
            # 注册日志
            await setup_logging()

            yield
            # 在应用关闭时执行清理操作（如果需要）

        self.app = FastAPI(
            title=appSettings.app_name,
            version=appSettings.app_version,
            redoc_url=None,
            debug=True,
            lifespan=lifespan,
        )

        # 初始化 核心
        self.init_core()

    def init_core(self):
        # 挂载静态文件
        self.mount_static()
        # 注册中间件
        self.init_middleware()
        # 注册路由器
        self.init_router()

    def init_router(self):
        # 注册 Web 路由
        init_web_routers(self.app)
        # 注册 Api 路由
        init_api_routers(self.app)

    def init_middleware(self):
        """ 注册中间件 """
        # 注册 GZip 中间件pyt
        self.app.add_middleware(GZipMiddleware, minimum_size=300, compresslevel=5)
        # Cors
        self.app.add_middleware(
            CORSMiddleware,
            allow_origins=appSettings.cors_allow_origins,
            allow_credentials=appSettings.cors_allow_credentials,
            allow_methods=appSettings.cors_allow_methods,
            allow_headers=appSettings.cors_allow_headers,
        )

        async def add_process_time_header(request: Request, call_next):
            """ 添加执行时间 """
            start_time = time.time()
            response = await call_next(request)
            process_time = time.time() - start_time
            response.headers["X-Process-Time"] = str(process_time)

            return response

        # 添加执行时间
        self.app.middleware("http")(add_process_time_header)

    def mount_static(self):
        # 静态文件
        # 将public文件夹作为静态文件夹挂载到根目录
        self.app.mount('/web', StaticFiles(directory='storage/web', html=True), name='web')
        # static
        self.app.mount('/assets', StaticFiles(directory='storage/assets'), name='assets')

    def instance(self):
        return self.app


__all__ = ['Application']
